package com.lk.car.service.impl;

import com.lk.basic.constans.BaseConstants;
import com.lk.car.domain.CarDetail;
import com.lk.car.domain.CarResources;
import com.lk.car.domain.CarType;
import com.lk.car.mapper.CarDetailMapper;
import com.lk.car.mapper.CarResourcesMapper;
import com.lk.car.mapper.CarTypeMapper;
import com.lk.car.service.ICarTypeService;
import com.lk.basic.service.impl.BaseServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;


import java.io.Serializable;
import java.util.*;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author lk
 * @since 2022-11-04
 */
@Service
public class CarTypeServiceImpl extends BaseServiceImpl<CarType> implements ICarTypeService {

    @Autowired
    private CarTypeMapper carTypeMapper;

    @Autowired
    private CarDetailMapper carDetailMapper;

    @Autowired
    private CarResourcesMapper carResourcesMapper;


    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public List<CarType> tree(Long pid) {
        //Object o = redisTemplate.opsForValue().get(BaseConstants.CACHE_CARTYPE_IN_REDIS);
        List<CarType> o=getCacheDate(BaseConstants.CACHE_CARTYPE_IN_REDIS);
        if (Objects.nonNull(o)){
            return (List<CarType>) o;
        }
        synchronized (CarTypeServiceImpl.class){
            //o = redisTemplate.opsForValue().get(BaseConstants.CACHE_CARTYPE_IN_REDIS);
            o=getCacheDate(BaseConstants.CACHE_CARTYPE_IN_REDIS);
            if (Objects.nonNull(o)){
                return (List<CarType>) o;
            }
            List<CarType> carTypes=getCarTypesByLoop(pid);
            setCacheData(BaseConstants.CACHE_CARTYPE_IN_REDIS, carTypes);
            //redisTemplate.opsForValue().set(BaseConstants.CACHE_CARTYPE_IN_REDIS, carTypes);
            //redisTemplate.opsForValue().set(BaseConstants.CACHE_CARTYPE_IN_REDIS, new ArrayList<>());

            return carTypes;
        }

    }
    private void setCacheData(String key,List<CarType> carTypes){
        redisTemplate.opsForValue().set(key,carTypes);
        redisTemplate.opsForValue().set(key+"_bak",carTypes);

    }
    private List<CarType> getCacheDate(String key){
        Object o = redisTemplate.opsForValue().get(key);
        if (Objects.nonNull(o)){
            return (List<CarType>) o;
        }
        o = redisTemplate.opsForValue().get(key+"_bak");
        if (Objects.nonNull(o)){
            redisTemplate.opsForValue().set(key, o);
            return (List<CarType>) o;
        }
        return null;
    }

    @Override
    public void insert(CarType carType) {
        super.insert(carType);
        redisTemplate.delete(BaseConstants.CACHE_CARTYPE_IN_REDIS);
    }

    @Override
    public void update(CarType carType) {
        super.update(carType);
        redisTemplate.delete(BaseConstants.CACHE_CARTYPE_IN_REDIS);

    }

    @Override
    public void delete(Serializable id) {

        carResourcesMapper.deleteCarId(id);
        carDetailMapper.deleteCarId(id);
        super.delete(id);
        redisTemplate.delete(BaseConstants.CACHE_CARTYPE_IN_REDIS);

    }

    private List<CarType> getCarTypesByLoop(Long pid) {

        List<CarType> result=new ArrayList<>();
        // 1 查询出所有的类型
        List<CarType> allCarTypes=carTypeMapper.selAll();
        Map<Long,CarType>map = new HashMap<>();
        for (CarType allCarType : allCarTypes) {
            map.put(allCarType.getId(),allCarType);
        }
        // 2 遍历所有的类型
        for (CarType carType : allCarTypes) {
        // 2.1 如果类型的pid = 0,将它作为一级类型返回
            if (carType.getPid().longValue()==pid.longValue()){
                result.add(carType);
            }else {
        // 2.2 如果类型pid!=0,找到该类型节点的父类型,将它作为父类型的子节点,放到父类型中
        // 方案二: 将所有的类型都放入map中,map的key是类型的id value是cartype  时间复杂度:2*n
                // 直接从map中获取key=carType.getId()
                CarType parent = map.get(carType.getPid());
                // 将该节点放到父节点中
                parent.getChildren().add(carType);
            }
        }
        return result;
    }
    private List<CarType> getCarTypes(Long pid) {
        List<CarType> childs=carTypeMapper.loadByPid(pid);
        if (childs==null){
            return null;
        }
        for (CarType child : childs) {
            List<CarType> grandson=tree(child.getId());
            child.setChildren(grandson);
        }
        return childs;
    }
}
